cmake_minimum_required(VERSION 3.10)

project(service_box_framework VERSION 0.2.0)

IF (UNIX)
    find_package(ZLIB)
ENDIF ()

#search target source file 
aux_source_directory(argument SRC_FILES)
aux_source_directory(box SRC_FILES)
aux_source_directory(box/loop SRC_FILES)
aux_source_directory(box/loop/udp SRC_FILES)
aux_source_directory(box/loop/kcp SRC_FILES)
aux_source_directory(box/loop/http SRC_FILES)
aux_source_directory(config SRC_FILES)
aux_source_directory(detail SRC_FILES)
aux_source_directory(detail/zookeeper SRC_FILES)
aux_source_directory(detail/call_tracer SRC_FILES)
aux_source_directory(detail/call_tracer/reporter SRC_FILES)
aux_source_directory(detail/call_tracer/log SRC_FILES)
aux_source_directory(detail/call_tracer/kafka SRC_FILES)
aux_source_directory(util SRC_FILES)
aux_source_directory(util/websocket SRC_FILES)
aux_source_directory(util/lua SRC_FILES)
aux_source_directory(util/lua/argument SRC_FILES)
aux_source_directory(util/lua/config SRC_FILES)
aux_source_directory(util/lua/redis SRC_FILES)
aux_source_directory(util/lua/time SRC_FILES)
aux_source_directory(util/lua/http SRC_FILES)
aux_source_directory(util/lua/console SRC_FILES)
aux_source_directory(util/bucket_token SRC_FILES)
aux_source_directory(util/bucket_token/impl SRC_FILES)
aux_source_directory(util/module_loader SRC_FILES)
aux_source_directory(../thirdparty/src/jsoncpp SRC_FILES)
aux_source_directory(../thirdparty/src/kconfig/internal SRC_FILES)
aux_source_directory(../thirdparty/src/klogger/internal SRC_FILES)
aux_source_directory(../thirdparty/src/knet SRC_FILES)
aux_source_directory(../thirdparty/src/http_parser SRC_FILES)
aux_source_directory(../thirdparty/src/lua SRC_FILES)
aux_source_directory(../thirdparty/src/kcp SRC_FILES)
aux_source_directory(../thirdparty/src/sha1 SRC_FILES)
aux_source_directory(../thirdparty/src/base64 SRC_FILES)
aux_source_directory(../thirdparty/src/load_balancer SRC_FILES)
aux_source_directory(../thirdparty/src/rpc-backend-cpp/src SRC_FILES)
aux_source_directory(../thirdparty/src/rpc-backend-cpp/src/coroutine/detail SRC_FILES)

add_library(service_box ${SRC_FILES})
if (MSVC)
    set(CMAKE_DEBUG_POSTFIX d)
	add_executable(service_box_runtime
		${PROJECT_SOURCE_DIR}/../src/lib/lib_main.cpp
	)
    set_target_properties(service_box_runtime PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
else()
    add_executable(service_box_runtime
    	${SRC_FILES}
	    ${PROJECT_SOURCE_DIR}/../src/lib/lib_main.cpp
    )
    set_target_properties(service_box_runtime PROPERTIES DEBUG_POSTFIX d)
endif()

# set project cplusplus stander 
target_compile_features(service_box PUBLIC cxx_std_17)

#cross platfom file 
target_sources(service_box PRIVATE
    $<$<PLATFORM_ID:Windows>: ../thirdparty/src/rpc-backend-cpp/src/coroutine/windows/coroutine.cpp>
    $<$<PLATFORM_ID:Linux>: ../thirdparty/src/rpc-backend-cpp/src/coroutine/linux/coroutine.cpp>
)

IF (MSVC)
ELSE()
    find_program(CCACHE_PROGRAM ccache)
    if (CCACHE_PROGRAM)
        set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
    endif ()
    if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
        target_compile_options(service_box PUBLIC
            $<$<AND:$<PLATFORM_ID:Linux>,$<COMPILE_LANGUAGE:CXX>>: -Wno-overloaded-virtual -Wno-format-security>
        )
    else ()        
        target_compile_options(service_box PUBLIC
            $<$<PLATFORM_ID:Linux>: -Wno-stringop-overflow -Wno-string-plus-int>
        )
    endif()
ENDIF()

target_compile_options(service_box PUBLIC
	$<$<PLATFORM_ID:Linux>: -m64 -Wall -Wno-comment -Wno-unused-variable -Wno-format-security -fnon-call-exceptions -fPIC>
	$<$<AND:$<PLATFORM_ID:Linux>,$<COMPILE_LANGUAGE:CXX>>:-fpermissive -Wno-overloaded-virtual -Wno-format-security>
	$<$<PLATFORM_ID:Windows>: /wd4706 /wd4206 /wd4100 /wd4244 /wd4127 /wd4702 /wd4324 /wd4310 /wd4820 /W4 /MP /EHa>  #/permissive-
    )

target_compile_definitions(service_box PUBLIC
    USE_STATIC_LIB THREADED CURL_STATICLIB
    $<$<AND:$<PLATFORM_ID:Windows>,$<CONFIG:Debug>>:  _WINSOCK_DEPRECATED_NO_WARNINGS WIN32 _WINDOWS DEBUG _DEBUG _CONSOLE _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN>
    $<$<AND:$<PLATFORM_ID:Windows>,$<CONFIG:Release>>: _WINSOCK_DEPRECATED_NO_WARNINGS _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN WIN32 _WINDOWS NDEBUG>
    $<$<AND:$<PLATFORM_ID:Linux>,$<CONFIG:Debug>>: DEBUG _DEBUG LUA_USE_POSIX>
)

# set project cplusplus stander 
target_compile_features(service_box_runtime PUBLIC cxx_std_17)

#cross platfom file 
target_sources(service_box_runtime PRIVATE
    $<$<PLATFORM_ID:Windows>: ../thirdparty/src/rpc-backend-cpp/src/coroutine/windows/coroutine.cpp>
    $<$<PLATFORM_ID:Linux>: ../thirdparty/src/rpc-backend-cpp/src/coroutine/linux/coroutine.cpp>
)

IF (MSVC)
ELSE()
    if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
        target_compile_options(service_box_runtime PUBLIC
            $<$<AND:$<PLATFORM_ID:Linux>,$<COMPILE_LANGUAGE:CXX>>: -Wno-overloaded-virtual -Wno-format-security>
        )
    else ()
        target_compile_options(service_box_runtime PUBLIC
            $<$<PLATFORM_ID:Linux>: -Wno-stringop-overflow -Wno-string-plus-int>
        )
    endif()
ENDIF()

target_compile_options(service_box_runtime PUBLIC
    $<$<AND:$<PLATFORM_ID:Linux>,$<CONFIG:Debug>>: -g -O0 -m64 -Wall -Wno-comment -Wno-deprecated-declarations -Wno-format-security -fnon-call-exceptions -fsanitize=address -fsanitize=leak -fno-omit-frame-pointer -fPIC>
	$<$<AND:$<PLATFORM_ID:Linux>,$<CONFIG:Release>>: -g -O2 -m64 -Wall -Wno-comment -Wno-deprecated-declarations -Wno-format-security -fnon-call-exceptions -fPIC>
	$<$<AND:$<PLATFORM_ID:Linux>,$<COMPILE_LANGUAGE:CXX>>:-fpermissive -Wno-overloaded-virtual>
	$<$<PLATFORM_ID:Windows>: /wd4706 /wd4206 /wd4100 /wd4244 /wd4127 /wd4702 /wd4324 /wd4310 /wd4820 /W4 /MP /EHa>  #/permissive-
    )

target_compile_definitions(service_box_runtime PUBLIC
    USE_STATIC_LIB THREADED CURL_STATICLIB
    $<$<AND:$<PLATFORM_ID:Windows>,$<CONFIG:Debug>>:  _WINSOCK_DEPRECATED_NO_WARNINGS WIN32 _WINDOWS DEBUG _DEBUG _CONSOLE _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN>
    $<$<AND:$<PLATFORM_ID:Windows>,$<CONFIG:Release>>: _WINSOCK_DEPRECATED_NO_WARNINGS _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN WIN32 _WINDOWS NDEBUG>
    $<$<AND:$<PLATFORM_ID:Linux>,$<CONFIG:Debug>>: DEBUG _DEBUG LUA_USE_POSIX>
)


#设置包含路径以及安装时候的路径
target_include_directories(service_box
	PUBLIC
	${PROJECT_SOURCE_DIR}
	${PROJECT_SOURCE_DIR}/../thirdparty 
	${PROJECT_SOURCE_DIR}/../thirdparty/include 
	${PROJECT_SOURCE_DIR}/../thirdparty/include/zookeeper
	${PROJECT_SOURCE_DIR}/../thirdparty/include/lua
    #cross-platform
    $<$<PLATFORM_ID:Windows>: ${PROJECT_SOURCE_DIR}/../thirdparty/include/hiredis/win ${PROJECT_SOURCE_DIR}/../thirdparty/include/knet>
    $<$<PLATFORM_ID:Linux>: ${PROJECT_SOURCE_DIR}/../thirdparty/include/hiredis>
)

#设置包含路径以及安装时候的路径
target_include_directories(service_box_runtime
	PUBLIC
	${PROJECT_SOURCE_DIR}
	${PROJECT_SOURCE_DIR}/../thirdparty 
	${PROJECT_SOURCE_DIR}/../thirdparty/include 
	${PROJECT_SOURCE_DIR}/../thirdparty/include/zookeeper
	${PROJECT_SOURCE_DIR}/../thirdparty/include/lua
    #cross-platform
    $<$<PLATFORM_ID:Windows>: ${PROJECT_SOURCE_DIR}/../thirdparty/include/hiredis/win ${PROJECT_SOURCE_DIR}/../thirdparty/include/knet>
    $<$<PLATFORM_ID:Linux>: ${PROJECT_SOURCE_DIR}/../thirdparty/include/hiredis>
)

IF (MSVC)
	foreach(var
	  CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
	  CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
	  CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
	  CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO
	)
    if(${var} MATCHES "/MD")
      string(REGEX REPLACE "/MD" "/MT" ${var} "${${var}}")
	endif()
	endforeach()
    set_target_properties(service_box_runtime PROPERTIES LINK_FLAGS "/ignore:4099")
	target_link_libraries(service_box_runtime PUBLIC
		debug ${PROJECT_SOURCE_DIR}/../build/Debug/service_box.lib optimized ${PROJECT_SOURCE_DIR}/../build/Release/service_box.lib
		debug ${PROJECT_SOURCE_DIR}/../thirdparty/lib/win/debug/libcurl.a optimized ${PROJECT_SOURCE_DIR}/../thirdparty/lib/win/release/libcurl.a
		debug ${PROJECT_SOURCE_DIR}/../thirdparty/lib/win/debug/zookeeper.lib optimized ${PROJECT_SOURCE_DIR}/../thirdparty/lib/win/release/zookeeper.lib
		debug ${PROJECT_SOURCE_DIR}/../thirdparty/lib/win/debug/hashtable.lib optimized ${PROJECT_SOURCE_DIR}/../thirdparty/lib/win/release/hashtable.lib
		debug ${PROJECT_SOURCE_DIR}/../thirdparty/lib/win/debug/libprotobufd.lib optimized ${PROJECT_SOURCE_DIR}/../thirdparty/lib/win/release/libprotobuf.lib	
		debug ${PROJECT_SOURCE_DIR}/../thirdparty/lib/win/debug/hiredis.lib optimized ${PROJECT_SOURCE_DIR}/../thirdparty/lib/win/release/hiredis.lib
		debug ${PROJECT_SOURCE_DIR}/../thirdparty/lib/win/debug/Win32_Interop.lib optimized ${PROJECT_SOURCE_DIR}/../thirdparty/lib/win/release/Win32_Interop.lib
		wldap32.lib
		ws2_32.lib
		psapi.lib	
	)
else()
	link_directories(${PROJECT_SOURCE_DIR}/../thirdparty/lib/linux)
    
    if (ZLIB_FOUND)
        target_link_libraries(service_box_runtime PUBLIC
            "$<$<AND:$<PLATFORM_ID:Linux>,$<CONFIG:Debug>>:asan>"
            ${PROJECT_SOURCE_DIR}/../thirdparty/lib/linux/libprotobuf.a
            ${PROJECT_SOURCE_DIR}/../thirdparty/lib/linux/libzookeeper.a
            ${PROJECT_SOURCE_DIR}/../thirdparty/lib/linux/libhashtable.a
            ${PROJECT_SOURCE_DIR}/../thirdparty/lib/linux/libcurl.a
            ${ZLIB_LIBRARIES}
            ${PROJECT_SOURCE_DIR}/../thirdparty/lib/linux/libhiredis.a
            -lpthread
            -ldl
        )
    else ()
        target_link_libraries(service_box_runtime PUBLIC
            "$<$<AND:$<PLATFORM_ID:Linux>,$<CONFIG:Debug>>:asan>"
            ${PROJECT_SOURCE_DIR}/../thirdparty/lib/linux/libprotobuf.a
            ${PROJECT_SOURCE_DIR}/../thirdparty/lib/linux/libzookeeper.a
            ${PROJECT_SOURCE_DIR}/../thirdparty/lib/linux/libhashtable.a
            ${PROJECT_SOURCE_DIR}/../thirdparty/lib/linux/libcurl.a
            ${PROJECT_SOURCE_DIR}/../thirdparty/lib/linux/libz.a
            ${PROJECT_SOURCE_DIR}/../thirdparty/lib/linux/libhiredis.a
            -lpthread
            -ldl
        )
    endif ()
endif()

install(TARGETS service_box
	ARCHIVE DESTINATION lib #设置安装路径
	)
	
# TODO Windows平台区分debug,release版本
install(TARGETS service_box_runtime
	RUNTIME DESTINATION bin #设置安装路径
	)

#因为工程结构不是按照cmake标准设计的，所以这里手动处理下include里面的目录结构
FILE(GLOB SUB_FILES RELATIVE ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/*)
SET(HEADER_DIR "")
FOREACH(child ${SUB_FILES})
	IF(IS_DIRECTORY ${PROJECT_SOURCE_DIR}/${child})
		LIST(APPEND HEADER_DIR ${PROJECT_SOURCE_DIR}/${child})
	ENDIF()
ENDFOREACH()

#install 
install(DIRECTORY  ${HEADER_DIR}
	DESTINATION  include
	FILES_MATCHING REGEX "\\.(h|hh|hpp)$"
	PATTERN "repo/*" EXCLUDE
	PATTERN "CMakeFiles/*" EXCLUDE
	)

if (MSVC)
install(DIRECTORY ${PROJECT_SOURCE_DIR}/../thirdparty/include ${PROJECT_SOURCE_DIR}/../thirdparty/lib
	DESTINATION thirdparty
	PATTERN "linux/*" EXCLUDE
	)
else()
install(DIRECTORY ${PROJECT_SOURCE_DIR}/../thirdparty/include ${PROJECT_SOURCE_DIR}/../thirdparty/lib
	DESTINATION thirdparty
	PATTERN "win/*" EXCLUDE
	)
endif()

add_subdirectory(sdk)


